
'--------------------------------------------------------
' 执行所有测试用例
'--------------------------------------------------------
Private Sub test_sqlTokenExtractor_ALL_case()
    ' ==================================================
    ' 注释测试
    ' ==================================================
    ' 测试: analyze 注释是有意义 token
    test_analyze_comment_has_mean
    ' 测试: analyze 注释是有意义 token + 测试多行注释
    ' 需要测试多行注释前面无空格 + 有空格的情况
    test_analyze_comment_has_mean_and_multiLineComment

    ' 测试: analyze 注释是有意义 token + 测试多行注释 + 不需要保留所有元素
    ' 需要测试多行注释前面无空格 + 有空格的情况
    test_analyze_comment_has_mean_and_multiLineComment_saveOnlyMeanToken

    ' 测试: analyzeMultiSql 注释是有意义 token
    test_analyzeMultiSql_comment_has_mean

    ' 测试: analyzeMultiSql 注释是有意义 token + 测试多行注释
    ' 需要测试多行注释前面无空格 + 有空格的情况
    test_analyzeMultiSql_comment_has_mean_and_multiLineComment

    ' ==================================================
    ' analyzeMultiSql -- 解析sql并按照分号来分隔多个sql
    ' ==================================================
    test_analyzeMultiSql_needSemicolon_true
    test_analyzeMultiSql_needSemicolon_false
End Sub

'--------------------------------------------------------
' 测试注释分割
'--------------------------------------------------------
' 测试: analyze 注释是有意义 token
Private Sub test_analyze_comment_has_mean()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    extractor.setSqlCommentIsMeanToken True

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "--comment0" & vbCrLF & _
            "select * from x1 --comment1" & vbCrLF & _
            "--comment2"
    extractor.analyze sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim tokenList As IObjArrayRef

    '-----------------------------------
    ' 检验结果--只检查有意义 token
    '-----------------------------------
    Set tokenList = extractor.meaningfulTokens
    Debug.Assert tokenList.Count = 7
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(4).value = "x1"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(5).value = "--comment1"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "--comment2"

    '-----------------------------------
    ' 检验结果--检查所有 token
    '-----------------------------------
    Set tokenList = extractor.allTokens
    Debug.Assert tokenList.Count = 13
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"

    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(1).value = vbCrLF

    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_SELECT

    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(3).value = " "

    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.ASTERISK

    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(5).value = " "

    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.KEY_FROM

    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(7).value = " "

    Debug.Assert tokenList.Item(8).value = "x1"

    Debug.Assert tokenList.Item(9).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(9).value = " "

    Debug.Assert tokenList.Item(10).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(10).value = "--comment1"

    Debug.Assert tokenList.Item(11).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(11).value = vbCrLF

    Debug.Assert tokenList.Item(12).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(12).value = "--comment2"
End Sub

' 测试: analyze 注释是有意义 token + 测试多行注释
' 需要测试多行注释前面无空格 + 有空格的情况
Private Sub test_analyze_comment_has_mean_and_multiLineComment()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    extractor.setSqlCommentIsMeanToken True

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "--comment0" & vbCrLF & _
            "select * from x1 --comment1" & vbCrLF & _
            " --comment2"
    ' 测试多行注释前没有空格 + 第一行是单独一行的注释
    sql = sql & vbCrLf & _
            "x2" & vbCrLF & _
            "/*" & vbCrLF & _
            "1234" & vbCrLF & _
            "abcd" & vbCrLF & _
            "*/"
    ' 测试多行注释前有空格 + 第一行是和前一个元素在同一行的注释
    sql = sql & vbCrLF & _
            "x3 /*" & vbCrLF & _
            "    9876" & vbCrLF & _
            "    wxyz" & vbCrLF & _
            "    */"
    extractor.analyze sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim tokenList As IObjArrayRef

    '-----------------------------------
    ' 检验结果--只检查有意义 token
    '-----------------------------------
    Set tokenList = extractor.meaningfulTokens
    Debug.Assert tokenList.Count = 17
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(4).value = "x1"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(5).value = "--comment1"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "--comment2"
    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(7).value = "x2"
    Debug.Assert tokenList.Item(8).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(8).value = "/*"
    Debug.Assert tokenList.Item(9).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(9).value = " 1234"
    Debug.Assert tokenList.Item(10).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(10).value = " abcd"
    Debug.Assert tokenList.Item(11).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(11).value = " */"
    Debug.Assert tokenList.Item(12).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(12).value = "x3"
    Debug.Assert tokenList.Item(13).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(13).value = "/*"
    Debug.Assert tokenList.Item(14).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(14).value = " 9876"
    Debug.Assert tokenList.Item(15).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(15).value = " wxyz"
    Debug.Assert tokenList.Item(16).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(16).value = " */"

    '-----------------------------------
    ' 检验结果--检查所有 token
    '-----------------------------------
    Set tokenList = extractor.allTokens
    Debug.Assert tokenList.Count = 36
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"

    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(1).value = vbCrLF

    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_SELECT

    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(3).value = " "

    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.ASTERISK

    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(5).value = " "

    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.KEY_FROM

    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(7).value = " "

    Debug.Assert tokenList.Item(8).value = "x1"

    Debug.Assert tokenList.Item(9).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(9).value = " "

    Debug.Assert tokenList.Item(10).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(10).value = "--comment1"

    Debug.Assert tokenList.Item(11).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(11).value = vbCrLF & " "

    Debug.Assert tokenList.Item(12).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(12).value = "--comment2"

    Debug.Assert tokenList.Item(13).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(13).value = vbCrLF

    Debug.Assert tokenList.Item(14).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(14).value = "x2"

    Debug.Assert tokenList.Item(15).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(15).value = vbCrLF

    ' 检查第一个多行注释
    Debug.Assert tokenList.Item(16).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(16).value = "/*"
    Debug.Assert tokenList.Item(17).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(17).value = vbCrLF
    Debug.Assert tokenList.Item(18).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(18).value = " 1234"
    Debug.Assert tokenList.Item(19).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(19).value = vbCrLF
    Debug.Assert tokenList.Item(20).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(20).value = " abcd"
    Debug.Assert tokenList.Item(21).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(21).value = vbCrLF
    Debug.Assert tokenList.Item(22).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(22).value = " */"
    Debug.Assert tokenList.Item(23).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(23).value = vbCrLF

    ' 检查第二个多行注释
    Debug.Assert tokenList.Item(24).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(24).value = "x3"

    Debug.Assert tokenList.Item(25).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(25).value = " "

    Debug.Assert tokenList.Item(26).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(26).value = "/*"
    Debug.Assert tokenList.Item(27).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(27).value = vbCrLF

    Debug.Assert tokenList.Item(28).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(28).value = "   "
    Debug.Assert tokenList.Item(29).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(29).value = " 9876"
    Debug.Assert tokenList.Item(30).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(30).value = vbCrLF

    Debug.Assert tokenList.Item(31).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(31).value = "   "
    Debug.Assert tokenList.Item(32).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(32).value = " wxyz"
    Debug.Assert tokenList.Item(33).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(33).value = vbCrLF

    Debug.Assert tokenList.Item(34).tokenType = SqlTokenType.NO_MEAN
    Debug.Assert tokenList.Item(34).value = "   "
    Debug.Assert tokenList.Item(35).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(35).value = " */"

End Sub

' 测试: analyze 注释是有意义 token + 测试多行注释 + 不需要保留所有元素
' 需要测试多行注释前面无空格 + 有空格的情况
Private Sub test_analyze_comment_has_mean_and_multiLineComment_saveOnlyMeanToken()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init False

    extractor.setSqlCommentIsMeanToken True

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "--comment0" & vbCrLF & _
            "select * from x1 --comment1" & vbCrLF & _
            "--comment2"
    ' 测试多行注释前没有空格 + 第一行是单独一行的注释
    sql = sql & vbCrLf & _
            "x2" & vbCrLF & _
            "/*" & vbCrLF & _
            "1234" & vbCrLF & _
            "abcd" & vbCrLF & _
            "*/"
    ' 测试多行注释前有空格 + 第一行是和前一个元素在同一行的注释
    sql = sql & vbCrLF & _
            "x3 /*" & vbCrLF & _
            "    9876" & vbCrLF & _
            "    wxyz" & vbCrLF & _
            "    */"
    extractor.analyze sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim tokenList As IObjArrayRef

    '-----------------------------------
    ' 检验结果--只检查有意义 token
    '-----------------------------------
    Set tokenList = extractor.meaningfulTokens
    Debug.Assert tokenList.Count = 17
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(4).value = "x1"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(5).value = "--comment1"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "--comment2"
    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(7).value = "x2"
    Debug.Assert tokenList.Item(8).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(8).value = "/*"
    Debug.Assert tokenList.Item(9).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(9).value = " 1234"
    Debug.Assert tokenList.Item(10).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(10).value = " abcd"
    Debug.Assert tokenList.Item(11).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(11).value = " */"
    Debug.Assert tokenList.Item(12).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(12).value = "x3"
    Debug.Assert tokenList.Item(13).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(13).value = "/*"
    Debug.Assert tokenList.Item(14).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(14).value = " 9876"
    Debug.Assert tokenList.Item(15).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(15).value = " wxyz"
    Debug.Assert tokenList.Item(16).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(16).value = " */"

    '-----------------------------------
    ' 检验结果--检查所有 token 为空
    '-----------------------------------
    Set tokenList = extractor.allTokens
    Debug.Assert tokenList Is Nothing

End Sub

' 测试: analyzeMultiSql 注释是有意义 token
Private Sub test_analyzeMultiSql_comment_has_mean()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    extractor.setSqlCommentIsMeanToken True

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "--comment0" & vbCrLF & _
            "select * from x1 --comment1" & vbCrLF & _
            "--comment2" & vbCrLF & _
            ";select * from x2 --comment3" & vbCrLf & _
            ";select * from x3 --comment4"
    extractor.analyzeMultiSql sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim multiMeaningfulTokens As IObjArrayRef
    Set multiMeaningfulTokens = extractor.multiMeaningfulTokens

    ' 4. 获取所有 token 数组引用，包括: 有意义的 sql token + 无意义的分隔符
    Dim multiAllTokens As IObjArrayRef
    Set multiAllTokens = extractor.multiAllTokens

    '-----------------------------------
    ' 检验结果
    '-----------------------------------
    Dim tokenList As IObjArrayRef
    Dim token As SqlToken
    Debug.Assert multiMeaningfulTokens.Count = 3

    ' 检验第一个 sql
    Set tokenList = multiMeaningfulTokens.Item(0)
    Debug.Assert tokenList.Count = 8
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(4).value = "x1"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(5).value = "--comment1"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "--comment2"
    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.SEMICOLON
    ' 检验第二个 sql
    Set tokenList = multiMeaningfulTokens.Item(1)
    Debug.Assert tokenList.Count = 6
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x2"
    '     测试非换行注释
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(4).value = "--comment3"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SEMICOLON
    ' 检验第三个 sql
    Set tokenList = multiMeaningfulTokens.Item(2)
    Debug.Assert tokenList.Count = 5
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x3"
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(4).value = "--comment4"
End Sub

' 测试: analyzeMultiSql 注释是有意义 token + 测试多行注释
' 需要测试多行注释前面无空格 + 有空格的情况
Private Sub test_analyzeMultiSql_comment_has_mean_and_multiLineComment()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    extractor.setSqlCommentIsMeanToken True

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "--comment0" & vbCrLF & _
            "select * from x1 --comment1" & vbCrLF & _
            "--comment2" & vbCrLF & _
            ";select * from x2 --comment3" & vbCrLf & _
            ";select * from x3 --comment4"
    ' 测试多行注释前没有空格 + 第一行是单独一行的注释
    sql = sql & vbCrLf & _
            "x4" & vbCrLF & _
            "/*" & vbCrLF & _
            "1234" & vbCrLF & _
            "abcd" & vbCrLF & _
            "*/"
    ' 测试多行注释前有空格 + 第一行是和前一个元素在同一行的注释
    sql = sql & vbCrLF & _
            "x5 /*" & vbCrLF & _
            "    9876" & vbCrLF & _
            "    wxyz" & vbCrLF & _
            "    */"

    extractor.analyzeMultiSql sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim multiMeaningfulTokens As IObjArrayRef
    Set multiMeaningfulTokens = extractor.multiMeaningfulTokens

    ' 4. 获取所有 token 数组引用，包括: 有意义的 sql token + 无意义的分隔符
    Dim multiAllTokens As IObjArrayRef
    Set multiAllTokens = extractor.multiAllTokens

    '-----------------------------------
    ' 检验结果
    '-----------------------------------
    Dim tokenList As IObjArrayRef
    Dim token As SqlToken
    Debug.Assert multiMeaningfulTokens.Count = 3

    ' 检验第一个 sql
    Set tokenList = multiMeaningfulTokens.Item(0)
    Debug.Assert tokenList.Count = 8
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(0).value = "--comment0"
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(3).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(4).value = "x1"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(5).value = "--comment1"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "--comment2"
    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.SEMICOLON
    ' 检验第二个 sql
    Set tokenList = multiMeaningfulTokens.Item(1)
    Debug.Assert tokenList.Count = 6
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x2"
    '     测试非换行注释
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(4).value = "--comment3"
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.SEMICOLON

    ' 检验第三个 sql
    Set tokenList = multiMeaningfulTokens.Item(2)
    Debug.Assert tokenList.Count = 15
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x3"
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(4).value = "--comment4"

    ' 检验第三个 sql -- 检查第一个多行注释
    Debug.Assert tokenList.Item(5).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(5).value = "x4"
    Debug.Assert tokenList.Item(6).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(6).value = "/*"
    Debug.Assert tokenList.Item(7).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(7).value = " 1234"
    Debug.Assert tokenList.Item(8).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(8).value = " abcd"
    Debug.Assert tokenList.Item(9).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(9).value = " */"
    ' 检验第三个 sql -- 检查第二个多行注释
    Debug.Assert tokenList.Item(10).tokenType = SqlTokenType.STR_NAME
    Debug.Assert tokenList.Item(10).value = "x5"
    Debug.Assert tokenList.Item(11).tokenType = SqlTokenType.SHARE_LINE_COMMENT
    Debug.Assert tokenList.Item(11).value = "/*"
    Debug.Assert tokenList.Item(12).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(12).value = " 9876"
    Debug.Assert tokenList.Item(13).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(13).value = " wxyz"
    Debug.Assert tokenList.Item(14).tokenType = SqlTokenType.SINGLE_LINE_COMMENT
    Debug.Assert tokenList.Item(14).value = " */"
End Sub

'--------------------------------------------------------
' analyzeMultiSql -- 解析sql并按照分号来分隔多个sql
'--------------------------------------------------------
' 保留 ;
Private Sub test_analyzeMultiSql_needSemicolon_true()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "select * from x1;select * from x2 --comment" & vbCrLf & _
          ";select * from x3"
    extractor.analyzeMultiSql sql

    ' 3. 获取所有的有意义的 token 数组引用
    Dim multiMeaningfulTokens As IObjArrayRef
    Set multiMeaningfulTokens = extractor.multiMeaningfulTokens

    ' 4. 获取所有 token 数组引用，包括: 有意义的 sql token + 无意义的分隔符
    Dim multiAllTokens As IObjArrayRef
    Set multiAllTokens = extractor.multiAllTokens

    '-----------------------------------
    ' 检验结果
    '-----------------------------------
    Dim tokenList As IObjArrayRef
    Dim token As SqlToken
    Debug.Assert multiMeaningfulTokens.Count = 3

    ' 检验第一个 sql
    Set tokenList = multiMeaningfulTokens.Item(0)
    Debug.Assert tokenList.Count = 5
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x1"
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SEMICOLON
    ' 检验第二个 sql
    Set tokenList = multiMeaningfulTokens.Item(1)
    Debug.Assert tokenList.Count = 5
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x2"
    Debug.Assert tokenList.Item(4).tokenType = SqlTokenType.SEMICOLON
    ' 检验第三个 sql
    Set tokenList = multiMeaningfulTokens.Item(2)
    Debug.Assert tokenList.Count = 4
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x3"
End Sub

' 不保留 ;
Private Sub test_analyzeMultiSql_needSemicolon_false()
    ' 1. 创建 token 提取器，并初始化
    Dim extractor As SqlTokenExtractor
    Set extractor = New SqlTokenExtractor
    extractor.Init

    ' 2. 解析指定的 sql 字符串
    Dim sql As String
    sql = "select * from x1;select * from x2;select * from x3"
    extractor.analyzeMultiSql sql, false

    ' 3. 获取所有的有意义的 token 数组引用
    Dim multiMeaningfulTokens As IObjArrayRef
    Set multiMeaningfulTokens = extractor.multiMeaningfulTokens

    ' 4. 获取所有 token 数组引用，包括: 有意义的 sql token + 无意义的分隔符
    Dim multiAllTokens As IObjArrayRef
    Set multiAllTokens = extractor.multiAllTokens

    '-----------------------------------
    ' 检验结果
    '-----------------------------------
    Dim tokenList As IObjArrayRef
    Dim token As SqlToken
    Debug.Assert multiMeaningfulTokens.Count = 3

    ' 检验第一个 sql
    Set tokenList = multiMeaningfulTokens.Item(0)
    Debug.Assert tokenList.Count = 4
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x1"

    ' 检验第二个 sql
    Set tokenList = multiMeaningfulTokens.Item(1)
    Debug.Assert tokenList.Count = 4
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x2"

    ' 检验第三个 sql
    Set tokenList = multiMeaningfulTokens.Item(2)
    Debug.Assert tokenList.Count = 4
    Debug.Assert tokenList.Item(0).tokenType = SqlTokenType.KEY_SELECT
    Debug.Assert tokenList.Item(1).tokenType = SqlTokenType.ASTERISK
    Debug.Assert tokenList.Item(2).tokenType = SqlTokenType.KEY_FROM
    Debug.Assert tokenList.Item(3).value = "x3"
End Sub